package cn.biplam.common.wrapper;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import cn.biplam.common.tools.TOOLS;

/**
 * 含有列索引的行数未知，列数已知的2维表<br>
 * <ul>用法：
 * <li> 创建二维表 new D2KArray ("列索引") 列索引为每列对应的列名 
 * <li> 插入内容   this.put("行数据") 
 * <li> 获取二维表数据<br> 
 *        while(this.next){<br>
 *        	 this.get("列下标"); 或者 this.get("列名");<br>
 *        } <br>
 * @author XiaoRuxing 2009-6-20下午01:35:36
 * @version 1.0
 */
public class D2KArray<M> implements Serializable,Result{
	
	private static final long serialVersionUID = 8856413320386442L;

	/** 存储包含行索引的二维表 */	
	private ArrayList<M[]> table;

	/** 存储列名称索引 */	
	private ArrayList<String> aColNameIndex;
	/** 列数 */	
	private int iColNumber;  
	/** 行数 */	
	private int iRowNumber; 
	
	/** 当前访问的行索引 */
	private int iCurrentRow;
	
	/**
	 * 创建二维表
	 * @param kvmColNameIndex 列索引
	 */
	public D2KArray(ArrayList<String> aColNameIndex){
		table=new ArrayList<M[]>();
		setColNameIndex(aColNameIndex);
		this.iRowNumber=0;
		this.iCurrentRow=-1;
	}
	
	/**
	 * 初始化列索引
	 * @param kvmColNameIndex
	 */
	public void setColNameIndex(ArrayList<String> aColNameIndex){

		this.aColNameIndex=aColNameIndex;
		/** 设置列数 */
		this.iColNumber=aColNameIndex.size();
	}
	
	/**
	 * 添加表行
	 * @param mValue         值数组
	 * @throws ErrorMessage  如果插入数组的列数不等于对象列数，抛出异常
	 */
	public void put(M... mValue) throws ErrorMessage{

		/** 如果插入数组的列数不等于对象列数，抛出异常 */
		if(mValue.length!=iColNumber){
			throw new ErrorMessage("The number of column is out of bound!");
		}
		this.table.add(mValue);
		this.iRowNumber=table.size();
	}
	
	/**
	 * 获取指定行数据
	 * @param iRowIndex 行下标 行下标从0开始  0,1,2...
	 * @return 指定行
	 * @throws ErrorMessage 
	 */
	public M[] getRow(int iRowIndex) throws ErrorMessage{
		rowRangeCheck(iRowIndex);
		return this.table.get(iRowIndex);
	}

	/**
	 * 返回指定列记录
	 * @param iRowIndex  行序号  行下标从0开始  0,1,2...     
	 * @param iColIndex  列序号  列下标从0开始  0,1,2...
	 * @return  
	 * @throws ErrorMessage 如果列下标越界返回异常
	 */
	public M getCol(int iRowIndex,int iColIndex) throws ErrorMessage{
		rowRangeCheck(iRowIndex);
		colRangeCheck(iColIndex);
		return table.get(iRowIndex)[iColIndex];
	}

	/**
	 * 返回指定列记录
	 * @param iRowIndex 行序号 行下标从0开始  0,1,2...
	 * @param sColName 列名
	 * @return 
	 * @throws ErrorMessage 如果列名不存在返回异常
	 */
	public M getCol(int iRowIndex,String sColName) throws ErrorMessage{

		/** 获取列编号 */
		int colIndex=this.getColumnIndex(sColName);
		rowRangeCheck(iRowIndex);
		colRangeCheck(colIndex);
		return this.getCol(iRowIndex, colIndex);
	}

	/**
	 * 获取列名的列编号 
	 * @param sColName 列名
	 * @return 列名的列编号
	 */
	public int getColumnIndex(String sColName){
		return aColNameIndex.indexOf(sColName);
	}
	
	/**
	 * 返回行数
	 * @return 二维表行数
	 */
	public int size(){
		return this.iRowNumber;
	}

	/**
	 * 返回列数
	 * @return 二维表列数
	 */
	public int getColCount(){
		return this.iColNumber;
	}
	
	/**
	 * 返回是否为空
	 * @return	是否为空
	 */
	public boolean isNull(){
		return iRowNumber==0;
	}

	/**
	 * 	删除指定行 
	 * @param iRowIndex 行
	 * @throws ErrorMessage 
	 * @throws 如果指定的行下标超过了现有的行数返回越界异常
	 */
	public void remove(int iRowIndex) throws ErrorMessage{
		rowRangeCheck(iRowIndex);
		table.remove(iRowIndex);
		iRowNumber--;
	}
	
	/**
	 * 判断列下标是否越界
	 * @param iColIndex	列号
	 */
	private void colRangeCheck(int iColIndex) throws ErrorMessage{
		if (iColIndex >= iColNumber || iColIndex < 0){
			throw new ErrorMessage("下标越界");
		}
	}

	/**
	 * 获取当前行
	 * @return 当前索引指向的行数据 
	 * @throws ErrorMessage 
	 */
	public M[] get() throws ErrorMessage{
		return this.getRow(this.iCurrentRow);
	}
	
	/**
	 * 获取当前行中指定列的值，列下标从0开始 
	 * @param iColIndex 列下标
	 * @return 指定列的值
	 * @throws ErrorMessage
	 */
	public M get(int iColIndex) throws ErrorMessage{
		return this.getCol(this.iCurrentRow, iColIndex);
	}
	
	/**
	 * 获取当前行中指定列的值 
	 * @param sColumnName 列名
	 * @return 指定列的值
	 * @throws ErrorMessage
	 */
	public M get(String sColumnName) throws ErrorMessage{
		return this.getCol(this.iCurrentRow, sColumnName);
	}
	
	/**
	 * 将光标从当前位置向前移一行
	 * @return 如果存在下一行则返回 true；如果不存在下一行则返回 false  
	 */
	public boolean next(){
		if(this.iCurrentRow>=this.size()-1){
			return false;
		}else{
			this.iCurrentRow++;
			return true;
		}
	}
	
	/**
	 * 将光标从当前位置向上一行 
	 * @return 如果存在上一行返回true;如果不存在上一行返回false
	 */
	public boolean previous(){
		if(this.iCurrentRow<=0){
			return false;
		}else{
			this.iCurrentRow--;
			return true;
		}
	}

	/**
	 * 将光标移动到第一行
	 * @return 如果记录集为空返回false,否则返回真
	 */
	public boolean first(){
		if(this.isNull()){
			return false;
		}else{
			this.iCurrentRow=0;
			return true;
		}
	}
	
	/**
	 * 将光标移动到最后一行 
	 * @return 如果记录集为空返回false,否则返回真
	 */
	public boolean last(){
		if(this.isNull()){
			return false;
		}else{
			this.iCurrentRow=this.size()-1;
			return false;
		}
	}
	
	/**
	 * 将光标移动到指定行
	 * @param row 行下标
	 * @return 如果存在指定下标行返回true,否则返回false
	 */
	public boolean absolute(int row){
		if(row>this.size()-1||row<0){
			return false;
		}else{
			this.iCurrentRow=row;
			return true;
		}
	}
	
	/**
	 * 获取当前访问行编号 
	 * @return 当前访问行编号,如果不存在返回-1
	 */
	public int getCurrentRow(){
		return this.iCurrentRow;
	}
	
	/**
	 * 判断行下标是否越界
	 * @param iRowIndex	行号
	 * @throws ErrorMessage 
	 */
	private void rowRangeCheck(int iRowIndex) throws ErrorMessage{
		if (iRowIndex >= iRowNumber || iRowIndex < 0){
			throw new ErrorMessage("下标越界");
		}
	}

	/**
	 * 获取当前行中指定列的布尔值  如果值为"0"返回false  如果值为"1"返回true 不在范围内抛出异常
	 * @param iColumnIndex 列下标
	 * @return 当前行中指定列的布尔值
	 * @throws ErrorMessage
	 */
	public boolean getBoolean(int columnIndex) throws ErrorMessage {
		M m = this.getCol(this.iCurrentRow, columnIndex);
		String colValue= null;
		if(m!=null){
			colValue = m.toString();
		}
		if("0".equals(colValue)){
			return false;
		}else if("1".equals(colValue)){
			return true;
		}else{
			return false;
		}
	}

	/**
	 * 获取当前行中指定列的布尔值  如果值为"0"返回false  如果值为"1"返回true 不在范围内抛出异常
	 * @param sColumnName 列名
	 * @return 当前行中指定列的布尔值
	 * @throws ErrorMessage
	 */
	public boolean getBoolean(String columnName) throws ErrorMessage {
		return this.getBoolean(this.getColumnIndex(columnName));
	}

	/**
	 * 获取当前行中指定列的整数值，列下标从0开始 
	 * @param iColumnIndex 列下标
	 * @return 指定列的值
	 * @throws ErrorMessage
	 */
	public int getInt(int columnIndex) throws ErrorMessage {
		M m = this.getCol(this.iCurrentRow, columnIndex);
		if(m!=null){
			return TOOLS.stringToInt(m.toString());
		}else{
			return -1;
		}
	}

	/**
	 * 获取当前行中指定列的整数值，列下标从0开始 
	 @param sColumnName 列名
	 * @return 指定列的值
	 * @throws ErrorMessage
	 */
	public int getInt(String columnName) throws ErrorMessage {
		return  this.getInt(this.getColumnIndex(columnName));
	}

	/**
	 * 获取当前行中指定列的字符值，列下标从0开始 
	 * @param iColIndex 列下标
	 * @return 指定列的值
	 * @throws ErrorMessage
	 */
	public String getString(int colIndex) throws ErrorMessage {
		M m = this.getCol(this.iCurrentRow, colIndex);
		if(m!=null){
			return m.toString();
		}else{
			return null;
		}
	}

	/**
	 * 获取当前行中指定列的字符值 
	 * @param sColumnName 列名
	 * @return 指定列的值
	 * @throws ErrorMessage
	 */
	public String getString(String columnName) throws ErrorMessage {
		return this.getString(this.getColumnIndex(columnName));
	}
	
	/**
	 * 将光标移动到最后一行之后
	 */
	public void afterLast() {
		this.iCurrentRow=this.size();
	}
	
	/**
	 * 将光标移动到第一行之前
	 */
	public void beforeFirst() {
		this.iCurrentRow=-1;
	}

	/**
	 * 查询是否存在字段
	 * @param columnName 字段名称
	 * @return 否存在字段
	 * @throws ErrorMessage
	 */
	public boolean existColumn(String columnName) throws ErrorMessage {
		int index = this.aColNameIndex.indexOf(columnName);
		if(index<0){
			return false;
		}else{
			return true;
		}
	}
	
	/**
	 * 
	 * @return 对象的字符串表达形式
	 */
	public String toString(){
		
		StringBuilder sp = new StringBuilder();
		
		Iterator<M[]> ite = this.table.iterator();
		
		M[] ent = null;
		
		/** head */
		if(ite.hasNext()){
			ent=ite.next();
			process(sp,ent);
		}

		/** Iterator */
		while(ite.hasNext()){
			sp.append("\n");
			ent=ite.next();
			process(sp,ent);
		}

		/** bottom */
		sp.append("\n");

		return sp.toString();
	}
	
	private void process(StringBuilder sb,M[] ent){
		/** 按照列名索引读取列数据 */
		for(int i=0;i<aColNameIndex.size();i++){
			sb.append(aColNameIndex.get(i));
			sb.append("=");
			sb.append(ent[i].toString());
			sb.append("\t");
		}
	}
}
